/*
 * Created on Feb 11, 2005
 * Created by dfhuynh
 */
package edu.mit.simile.longwell.query.project;

import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

import com.hp.hpl.jena.rdf.model.Literal;
import com.hp.hpl.jena.rdf.model.RDFNode;
import com.hp.hpl.jena.rdf.model.Resource;

import edu.mit.simile.SimileUtilities;
import edu.mit.simile.longwell.Profile;

/**
 * @author dfhuynh
 */
public class DateTimeProjector extends PropertyProjector {
	protected class DateTimePropertyProjection extends LongValueProjection 
		implements IDateTimeProjection {

		public DateTimePropertyProjection(Set objects) {
			super(
				DateTimeProjector.this.m_profile, 
				DateTimeProjector.this.m_property, 
				DateTimeProjector.this.m_forward, 
				DateTimeProjector.this.m_locale, objects);
		}

		/* (non-Javadoc)
		 * @see edu.mit.simile.longwell.query.IDateTimeProjection#getDate(com.hp.hpl.jena.rdf.model.Resource)
		 */
		public Date getDate(Resource object) {
			return (Date) getValue(object);
		}
		
		/* (non-Javadoc)
		 * @see edu.mit.simile.longwell.query.project.PropertyProjection#internalGetObjects(java.lang.Object)
		 */
		protected Set internalGetObjects(Object value) {
			Set		allObjects = getObjects();
			Set 	objects = new HashSet();
			Date 	date = (Date) value;
			
			Iterator i = allObjects.iterator();
			while (i.hasNext()) {
				Resource r = (Resource) i.next();
				if (datesEqual(date, (Date) getValue(r))) {
					objects.add(r);
				}
			}
			return objects;
		}
		
		/* (non-Javadoc)
		 * @see edu.mit.simile.longwell.query.project.PropertyProjection#nodeToValue(com.hp.hpl.jena.rdf.model.RDFNode)
		 */
		protected Object nodeToValue(RDFNode node) {
			return nodeToDate(node);
		}

		/* (non-Javadoc)
		 * @see edu.mit.simile.longwell.query.project.IDateTimeProjection#getEarliest()
		 */
		public Date getEarliest() {
			return new Date(internalGetMin());
		}

		/* (non-Javadoc)
		 * @see edu.mit.simile.longwell.query.project.IDateTimeProjection#getLatest()
		 */
		public Date getLatest() {
			return new Date(internalGetMax());
		}

		/* (non-Javadoc)
		 * @see edu.mit.simile.longwell.query.project.IDateTimeProjection#getObjects(java.util.Date, java.util.Date)
		 */
		public Set getObjects(Date fromInclusive, Date toExclusive) {
			return internalGetObjects(
				fromInclusive != null ? fromInclusive.getTime() : Long.MIN_VALUE,
				toExclusive != null ? toExclusive.getTime() : Long.MAX_VALUE);
		}

		/* (non-Javadoc)
		 * @see edu.mit.simile.longwell.query.project.IDateTimeProjection#countObjects(java.util.Date, java.util.Date)
		 */
		public int countObjects(Date fromInclusive, Date toExclusive) {
			return internalCountObjects(
					fromInclusive != null ? fromInclusive.getTime() : Long.MIN_VALUE,
					toExclusive != null ? toExclusive.getTime() : Long.MAX_VALUE);
		}

		/* (non-Javadoc)
		 * @see edu.mit.simile.longwell.query.project.LongValueProjection#valueToLong(java.lang.Object)
		 */
		protected long valueToLong(Object v) throws Exception {
			return ((Date) v).getTime();
		}
		
		/* (non-Javadoc)
		 * @see edu.mit.simile.longwell.query.project.ProjectionBase#internalGetObjectToValueMap()
		 */
		protected Map internalGetObjectToValueMap() {
			Map m = new HashMap();
			fillObjectToValueMap(m);
			return m;
		}

		@Override
		public String getProperty() {
			// TODO Auto-generated method stub
			return m_property.toString();
		}
	}
	
	/**
	 * @param profile
	 * @param parameter
	 */
	public DateTimeProjector(Profile profile, String parameter, String locale) {
		super(profile, parameter, locale);
	}
	
	/* (non-Javadoc)
	 * @see edu.mit.simile.longwell.query.project.PropertyProjector#isEfficientForRootProjection()
	 */
	public boolean isEfficientForRootProjection() {
		return false;
	}
	
	/* (non-Javadoc)
	 * @see edu.mit.simile.longwell.query.project.PropertyProjector#internalProject()
	 */
	protected IProjection internalProject() {
		return new DateTimePropertyProjection(null);
	}

	/* (non-Javadoc)
	 * @see edu.mit.simile.longwell.query.project.ProjectorBase#internalProject(java.util.Set)
	 */
	protected IProjection internalProject(Set objects) {
		return new DateTimePropertyProjection(objects);
	}
	
	final protected boolean datesEqual(Date date1, Date date2) {
		if (date1 == null) {
			return date2 == null;
		} else {
			return date1.equals(date2);
		}
	}
	
	final protected Date nodeToDate(RDFNode node) {
		if (node instanceof Literal) {
			return SimileUtilities.parseDate(((Literal) node).getString());
		}
		return null;
	}
}
